    package sha.pkg1;
import sha.pkg1.fnApoyo;

public class SHA1 {
     fnApoyo ayudante= new fnApoyo();
     String [] Kt={
            "01011010100000100111100110011001",   // 5A827999 para 0<t<19
            "01101110110110011110101110100001",   //6ED9EBA1 para 20<t<39
            "10001111000110111011110011011100",   //8F1BBCDC para 40<t<59
            "11001010011000101100000111010110"    //CA62C1D6 para 60<t<79
     };

 
     
    
 //Debe llegar texto como ASCII. Devuelve resultado de 448mod515+largo mensaje
public StringBuilder[] rellenar_448Mod512(String texto){
    
StringBuilder resultado[]= new StringBuilder[2];

//Mensaje convertido en binario y hexadecimal sin relleno aun 
resultado[0]= new StringBuilder(ayudante.AsciiToBinario(texto));
resultado[1]= new StringBuilder(ayudante.AsciiToHex(texto));


int largoM= texto.length();      //Largo mensaje en ASCII
int largoR=64;                   //Largo relleno por defecto de bloque de 64bytes= 512 bits
System.out.println("Largo Mensaje en bytes: "+largoM);

//Se busca un multiplo de 64 menos 8 que sea mayor estricto que el largo del mensaje en bytes
//o bien un multiplo de 512 menos 64 que sea mayor estricto que el largo del mensaje en bits
while((largoR-8)<= largoM){ 
    largoR=largoR+64;   
}
System.out.println("Largo Bloque multiplo de 512 en bytes: "+largoR);  //Largo de bloque multiplo de 512 obtenido


/***********************Relleno 448 mod 512***********************************/
//Agregamos el relleno para que quede de 448mod512 en Binario

for(int i=0; i< (largoR-largoM-8)*8; i++){
    if(i==0){  
    resultado[0].append("1");
    }
    else{
    resultado[0].append("0");
    }
}
System.out.println("Largo de Relleno en bits: "+ resultado[0].length());

//Agregamos el relleno para que quede de 448mod512 en Hexadecimal
for(int i=0; i< (largoR-largoM-8)*2; i++){
    if(i==0){  
    resultado[1].append("80");
    i++;
   }
    else{
    resultado[1].append("0");
    }
}


/*********************64 bits restantes *****************************************/
//Ahora se llenara el restante de 64bits con el largo en binario 
int tempD= (largoM+1)*8;  //cantidad elmentos en Binario, se obtiene un valor decimal
String l= ""+tempD;

/*********Largo en Binario**********/
String largo_binario= (ayudante.DecimalToBinario(l).toString());
int lenght_largo_binario= largo_binario.length();

for(int i=0; i< (64-lenght_largo_binario); i++){
    largo_binario= "0"+largo_binario;   
}
//Completo finalmente los 64 bits con el "largo" del mensaje
resultado[0]= new StringBuilder(resultado[0].append(largo_binario));


/**********Largo en Hexadecimal********/
String largo_hex= (ayudante.DecimalToHexadecimal(l));
int lenght_largo_hex= largo_hex.length();

for(int i=0; i< (16-lenght_largo_hex); i++){
    largo_hex= "0"+largo_hex;   
}
//Completo finalmente los 64 bits con el "largo" del mensaje
resultado[1]= new StringBuilder(resultado[1].append(largo_hex));



return resultado;

}

public StringBuilder rondas(StringBuilder bloqueActual){
 StringBuilder resultado= new StringBuilder();
  StringBuilder temp= new StringBuilder();
 
StringBuilder A= new StringBuilder  ("01100111010001010010001100000001");  //67452301
StringBuilder B = new StringBuilder ("11101111110011011010101110001001"); //EFCDAB89
StringBuilder C = new StringBuilder ("10011000101110101101110011111110");  //98BADCFE
StringBuilder D = new StringBuilder ("00010000001100100101010001110110"); //10325476
StringBuilder E = new StringBuilder ("11000011110100101110000111110000"); //C3D2E1F0


StringBuilder[] Wt= new StringBuilder[80];
 
StringBuilder[] primeras16= new StringBuilder[16];    
primeras16= ayudante.creaBloque(bloqueActual, 32);
 
 
for(int i=0;i <80; i++){
    if(i<=15){
    Wt[i]= new StringBuilder(primeras16[i]);
    }
    else{
    Wt[i]= ayudante.funcionXOR(Wt[i-3], Wt[i-8]);
    Wt[i]= ayudante.funcionXOR(Wt[i], Wt[i-14]);
    Wt[i]= ayudante.funcionXOR(Wt[i], Wt[i-16]);
    Wt[i]= ayudante.DesplazaBits(Wt[i], 1);   //Desplazar un bit a la izquierda
    
    }
    System.out.println("Wt["+i+"]: "+ Wt[i]);
}

StringBuilder desplazar= new StringBuilder();
StringBuilder funcion= new StringBuilder();
int K=-1;
for(int j=0;j<=79;j++){

    if(j<=19){
    //temp= A<<5 + F(1,B,C,D)+ E + Wt[j]+ Kt[1];
    funcion= new StringBuilder();
    funcion= F(1,B,C,D);
    K=0;
    
    }
    if(j>=20 && j<=39){
    //temp= A<<5 + F(2,B,C,D)+ E + Wt[j]+ Kt[2];
    funcion= new StringBuilder();
    funcion= F(2,B,C,D);
    K=1;
    }
    if(j>=40 && j<=59){
    //temp= A<<5 + F(3,B,C,D)+ E + Wt[j]+ Kt[3];
    funcion= new StringBuilder();
    funcion= F(3,B,C,D);
    K=2;
    }
    if(j>=60 && j<=79){
    //temp= A<<5 + F(4,B,C,D)+ E + Wt[j]+ Kt[4];
    funcion= new StringBuilder();
    funcion= F(4,B,C,D);
    K=3;
    }
    
    temp= new StringBuilder();
    desplazar= new StringBuilder();
    desplazar= ayudante.DesplazaBits(A, 5);
    
    temp= ayudante.funcionXOR(desplazar, funcion);
    temp= ayudante.funcionXOR(temp, E);
    temp=ayudante.funcionXOR(temp, Wt[j]);
    temp=ayudante.funcionXOR(temp, new StringBuilder(Kt[K]));
    System.out.println("j"+j+" :");
  
    //E=D;
    //D=C;
    //C=B<<30;
    //B=A;
    //A=temp;
   E=new StringBuilder(D);
   D= new StringBuilder(C);
   C= ayudante.DesplazaBits(B, 30);
   B= new StringBuilder(A);
   A= new StringBuilder(temp);
  System.out.println("A :"+A);
  System.out.println("B :"+B);
  System.out.println("C :"+C);
  System.out.println("D :"+D);
  System.out.println("E :"+E);
  
  
}
  //resultado= A+B+C+D+E;
 resultado= new StringBuilder(160);
 resultado.append(A.toString());
  resultado.append(B.toString());
   resultado.append(C.toString());
    resultado.append(D.toString());
     resultado.append(E.toString());
   
     return resultado;
}

public StringBuilder F(int i, StringBuilder B, StringBuilder C, StringBuilder D){
StringBuilder resultado= new StringBuilder();
StringBuilder temp1= new StringBuilder();
StringBuilder temp2= new StringBuilder();
StringBuilder temp3= new StringBuilder();

if(i==1){
//(b ^ c ) v ((not b)^ d)
temp1= ayudante.funcionAND(B,C);
temp2= ayudante.funcionNOT(B);
temp3= ayudante.funcionAND(temp2,D);
resultado= ayudante.funcionOR(temp1, temp3);
    
}
if(i==2){
//b XOR c XOR d
temp1=ayudante.funcionXOR(B, C);
resultado=ayudante.funcionXOR(temp1, D);
    
}
if(i==3){
//(b ^ c ) v (b ^ d) v (c ^ d)
temp1= ayudante.funcionAND(B, C);
temp2= ayudante.funcionAND(B, D);
temp3= ayudante.funcionAND(C, D);
temp1=ayudante.funcionOR(temp1, temp2);
resultado= ayudante.funcionOR(temp1, temp3);

}
if(i==4){
//b XOR c XOR d
temp1=ayudante.funcionXOR(B, C);
resultado=ayudante.funcionXOR(temp1, D);
}


return resultado;

}


}